import { commands } from '../util/command';
import { AndroidDevice } from '@/main/adb/android-device';
import { isIpAddr } from '@/util/device-utils';
import { NetworkUtils } from '@/util/network-utils';

function parseValue(valueStr: string) {
  return valueStr && valueStr.split(':')[1];
}

export function sleep(time: number) {
  return new Promise(resolve => setTimeout(resolve, time));
}

/**
 * 列出当前连接到电脑的设备
 */
export async function listDevices(): Promise<AndroidDevice[]> {
  const devices: AndroidDevice[] = [];
  const result = await commands.execCommand('adb devices -l');
  if (result) {
    result.split(/[\r\n]/).forEach(line => {
      if (!line || line.trim().length === 0 || /^\s*List of devices attached/i.test(line)) {
        return;
      }

      const [id, status, productStr, modelStr, deviceStr, transportIdStr] = line.split(/\s+/);
      const product = parseValue(productStr);
      const model = parseValue(modelStr);
      const device = parseValue(deviceStr);
      const transportId = parseValue(transportIdStr);

      devices.push({ id, status: status as any, product, model, device, transportId });
    });
  }

  return devices;
}

/**
 * 重连设备
 * @param deviceId 无线设备ID,如果传入的是有线设备,则将重连所有已经离线的设备
 */
export async function reconnectDevice(deviceId: string): Promise<string> {
  let cmd: string = 'adb reconnect offline';

  if (deviceId.indexOf(':') !== -1) {
    const [ip] = deviceId.split(':');
    if (isIpAddr(ip)) {
      cmd = `adb connect ${deviceId}`;
    }
  }
  return await commands.execCommand({ cmd, timeout: 1000 });
}

type ScanWirelessDeviceParam = {
  onprocess?: (event: { total: number; current: number }) => void;
  onend?: (event: { total: number; current: number }) => void;
};

/**
 * 扫描局域网中的无线设备
 */
export async function scanWirelessDevice(options?: ScanWirelessDeviceParam): Promise<void> {
  const localAddrs = NetworkUtils.getLocalIpAddrs(true);

  // 总的扫描数 = 本机ip数量 * 253(排除了电脑自身和255)
  let total = localAddrs.length * 253;
  let current = 0;
  let interval: any = null;

  if (typeof options?.onprocess === 'function') {
    interval = setInterval(() => {
      if (current >= total) {
        clearInterval(interval);
      }
      options!.onprocess!.call(null, { total, current });
    }, 1000);
  }

  const afterScan = () => current++;

  const step = 10;
  const estep = step - 1;

  for (const ip of localAddrs) {
    const dotLastIndex = ip.lastIndexOf('.') + 1;
    const self = +ip.substring(dotLastIndex);
    const prefix = ip.substring(0, dotLastIndex);

    for (let i = 1; i <= 254; i += step) {
      let end = i + estep;
      if (end > 254) {
        end = 254;
      }
      await scan(prefix, i, end, self, afterScan);
    }
  }

  clearInterval(interval);
  options?.onend?.call(null, { total, current: total });
}

async function scan(prefix: string, start: number, end: number, self: number, afterScan: () => void) {
  const promises: Promise<any>[] = [];
  for (let i = start; i <= end; i++) {
    const ip = prefix + i;
    console.log('scan: ', ip);
    promises.push(
      commands.execCommand({ cmd: `adb connect ${ip}`, reject: false, timeout: 600 }).finally(afterScan)
    );
  }

  await Promise.all(promises);
}
